#!/usr/bin/env python

"""
Dtella - Configuration Manager
Copyright (C) 2009-      Andrew Cooper <andyhhp@hotmail.com>

$Id$

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
"""

import types
from dtella.config.defaults import (LocalDefaults as LocalDefaults,
                                    BridgeDefaults as BridgeDefaults)

##
#@package dtella.config.config
#@authors Andrew Cooper
#
#@brief dtella configuration manager
#
#This manager acts as a central location for all static and dynamic
#configuration data

##
#@file config.py
#@authors Andrew Cooper
#
#@brief dtella configuration manager
#
#This manager acts as a central location for all static and dynamic
#configuration data

##
#@brief Manages all configuration data for dtella
#
#In charge of managing all configuation data and acts as a central access
#interface for the rest of the program
class ConfigManager:
    
    ## Boolean representing the presence of local_config.py
    __local_here = False
    ## Boolean reperesenting the presence of bridge_config.py
    __bridge_here = False
    
    ## Container for the local_config variables
    __local_vars = LocalDefaults()
    
    ##Container for the bridge_config variables
    __bridge_vars = BridgeDefaults()
    
    ##@brief Constructor
    #
    #Checks for the presence of local_config.py and optionally bridge_config.py
    #and overwrides the default values.  Also reads data from local ini file if
    #present.
    def __init__(self):
        
        try:
            import dtella.config.local_config
            __local_here = True
            self.LoadLocalVars()
        except ImportError:
            print "local_config not found"
            
        try:
            import dtella.config.bridge_config
            __bridge_here = True
            self.LoadBridgeVars()
        except ImportError:
            print "bridge_config not found"
            
        self.GenerateLocalAccessors()
        self.GenerateBridgeAccessors()
    
    ##@brief Getter function for __local_here
    #
    #Accessor function returing whether local_config.py is found.
    #@return True local_config.py is present
    #@return False local_config.py is missing
    #@see __local_here
    def LocalFound(self):
        return __local_here
    
    ##@brief Getter function for __bridge_here
    #
    #Accessor function returing whether bridge_config.py is found.
    #@return True bridge_config.py is present
    #@return False bridge_config.py is missing
    #@see __bridge_here
    def BridgeFound(self):
        return __bridge_here
    
    ##@brief Loads the variables from local_config.py
    #
    #Loads the variables from local_config.py into the __local_vars container
    def LoadLocalVars(self):
        
        import local_config as lcfg
        entities = [e for e in dir(lcfg) if not ((e[0:2] == "__")
                                or (type(getattr(lcfg,e)) == types.ModuleType))]
        
        for e in entities:
            if hasattr(ConfigManager.__local_vars,e):
                setattr(ConfigManager.__local_vars,e,getattr(lcfg,e))
            else:
                print "No attr", e#TODO replace with log

    ##@brief Creates accessor functions for all __local_vars elements
    #
    #Dynamically creates getter and setter functions for each element in
    #the __local_vars container.
    #
    #They are in the form @<class>.Get_<name>() and
    #@<class>.Set_<name>(<new value>).
    #
    #The setter contains type checking and raises TypeError if the new value is
    #not the same type as the old value
    def GenerateLocalAccessors(self):
        vars = [v for v in dir(ConfigManager.__local_vars) if v[0:2] != "__"]

        for v in vars:
            exec "def Getter():\n"\
                 " return getattr(ConfigManager._ConfigManager__local_vars,"\
                                                                "'%s')" % v
            setattr(self,"Get_%s"%v,Getter)
            
            exec "def Setter(val):\n"\
                 " vars = ConfigManager._ConfigManager__local_vars\n"\
                 " ex_type = type(getattr(vars,'%s'))\n"\
                 " if type(val) != ex_type:\n"\
                 "  raise TypeError('Expected %%s, got %%s in Set_%s'"\
                                "%%(str(ex_type),str(type(val))))\n"\
                 " setattr(vars,'%s',val)" % (v,v,v)
            setattr(self,"Set_%s"%v,Setter)
            
    ##@brief Loads the variables from bridge_config.py
    #
    #Loads the variables from bridge_config.py into the __bridge_vars container
    def LoadBridgeVars(self):
        
        import bridge_config as bcfg
        entities = [e for e in dir(bcfg) if not ((e[0:2] == "__")
                                or (type(getattr(bcfg,e)) == types.ModuleType))]
        
        for e in entities:
            if hasattr(ConfigManager.__bridge_vars,e):
                setattr(ConfigManager.__bridge_vars,e,getattr(bcfg,e))
            else:
                print "No attr", e#TODO: replace with log
    
    ##@brief Creates accessor functions for all __bridge_vars elements
    #
    #Dynamically creates getter and setter functions for each element in
    #the __bridge_vars container.
    #
    #They are in the form @<class>.Get_<name>() and
    #@<class>.Set_<name>(<new value>).
    #
    #The setter contains type checking and raises TypeError if the new value is
    #not the same type as the old value
    def GenerateBridgeAccessors(self):
        vars = [v for v in dir(ConfigManager.__bridge_vars) if v[0:2] != "__"]

        for v in vars:
            exec "def Getter():\n"\
                 " return getattr(ConfigManager._ConfigManager__bridge_vars,"\
                                                                "'%s')" % v
            setattr(self,"Get_%s"%v,Getter)
            
            exec "def Setter(val):\n"\
                 " vars = ConfigManager._ConfigManager__bridge_vars\n"\
                 " ex_type = type(getattr(vars,'%s'))\n"\
                 " if type(val) != ex_type:\n"\
                 "  raise TypeError('Expected %%s, got %%s in Set_%s'"\
                                "%%(str(ex_type),str(type(val))))\n"\
                 " setattr(vars,'%s',val)" % (v,v,v)
            setattr(self,"Set_%s"%v,Setter)
